package io.mqttpush.getway.http;

import io.mqttpush.getway.GetWayConstantBean;
import io.mqttpush.getway.common.CommonResponse;
import io.mqttpush.getway.common.Statistics;
import io.mqttpush.getway.http.controller.ControllBeans;
import io.mqttpush.getway.http.controller.Controller;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class AbHttpHandle extends ChannelInboundHandlerAdapter {

    Logger logger = LoggerFactory.getLogger(getClass());



    final String JSON_CONTENT_TYPE = "application/json";

    final ControllBeans controllbean = ControllBeans.getInstance();


    final GetWayConstantBean constantBean = GetWayConstantBean.instance();


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        FullHttpResponse response = new DefaultFullHttpResponse(
                HttpVersion.HTTP_1_1,
                HttpResponseStatus.INTERNAL_SERVER_ERROR);

        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
        cause.printStackTrace();
    }


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        /**
         * 前端连接数+1
         */
        Statistics.httpAbCount.incrementAndGet();
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);

        /**
         * 前端连接-1
         */
        Statistics.httpAbCount.decrementAndGet();


        if (logger.isDebugEnabled()) {
            logger.debug(ctx.channel() + "channelInactive");
        }
    }


    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {


        if (!(msg instanceof HttpRequest)) {
            ctx.write(CommonResponse.badResponse()).addListener(ChannelFutureListener.CLOSE);
            return;
        }


        HttpRequest request = (HttpRequest) msg;


        boolean keepAlive = HttpUtil.isKeepAlive(request);



        /**
         * 只允许post提交
         */
        if (request.method() != HttpMethod.POST) {
            ctx.write(CommonResponse.badResponse()).addListener(ChannelFutureListener.CLOSE);
            return;
        }


        if (!(request instanceof FullHttpRequest)) {
            ctx.write(CommonResponse.serErrResponse()).addListener(ChannelFutureListener.CLOSE);
            return;
        }



        /**
         * 应用业务调用
         */
        HttpResponse response= applyController(ctx.channel(), request);

        if (!keepAlive) {
            ctx.write(response).addListener(ChannelFutureListener.CLOSE);
        } else {
            response.headers().set(CommonResponse.CONNECTION, CommonResponse.KEEP_ALIVE);
            ctx.write(response);
        }


    }

    /**
     * 根据请求头决定应有的controller
     * 只支持JSON 文本请求 和mutilform 二进制请求
     *
     * @param channel
     * @param request
     * @return response
     */
    public HttpResponse applyController(Channel channel, HttpRequest request) {

        if (request == null) {
            return CommonResponse.badResponse();
        }

        String contentType = request.headers().get(CommonResponse.CONTENT_TYPE);
        Controller controller = null;

        if (contentType != null) {
            if (contentType.equalsIgnoreCase(JSON_CONTENT_TYPE)) {
                controller = controllbean.fullTextController();
            }
        }

        if (controller == null) {
            controller = controllbean.formController();
        }

        /**
         * 前端请求数+1
         */

        HttpResponse response=null;
        Statistics.httpReqCount.incrementAndGet();

        try{
            response=controller.service(channel, request);
        }catch (Throwable e){
            e.printStackTrace();
            response=  CommonResponse.serErrResponse();
        }

        return response;
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
        ctx.flush();
    }


}
